package com.ruoyi.util;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.cglib.beans.BeanCopier;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 对象拷贝工具类
 *
 * @author chenchuan2
 * @date 2022-12-16 15:00:24
 */
public class BeanCopierUtils {
    /**
     * BeanCopier 缓存Map
     */
    private static Map<String, BeanCopier> beanCopierCacheMap = new HashMap<>();

    /**
     * @param source 源对象
     * @param target 目标对象
     *               将source对象的属性拷贝到target对象中去
     * @date 2021/2/6
     */
    public static void copyProperties(Object source, Object target) {
        if (null == source) {
            return;
        }
        /** Map 缓存Key*/
        String cacheKey = source.getClass().toString() + target.getClass().toString();
        BeanCopier beanCopier = null;

        // 双重交易锁，防止并发问题发生
        if (!beanCopierCacheMap.containsKey(cacheKey)) {
            synchronized (BeanCopierUtils.class) {
                if (!beanCopierCacheMap.containsKey(cacheKey)) {
                    beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
                } else {
                    beanCopier = beanCopierCacheMap.get(cacheKey);
                }
            }
        } else {
            beanCopier = beanCopierCacheMap.get(cacheKey);
        }

        assert beanCopier != null;
        beanCopier.copy(source, target, null);
    }

    public static <T> T copyBean(Object source, Supplier<T> supplier) {
        T t = supplier.get();
        copyProperties(source, t);
        return t;
    }

    public static <T> T copyBean(Object source, Supplier<T> supplier, Consumer<T> after) {
        if (null == source) {
            return null;
        }
        T t = supplier.get();
        copyProperties(source, t);
        after.accept(t);
        return t;
    }

    /**
     * @param sources  源对象
     * @param supplier 目标类
     * @date 2021/2/6
     */
    public static <S, T> List<T> copyList(List<S> sources, Supplier<T> supplier) {
        if (CollectionUtils.isEmpty(sources)) {
            return Lists.newArrayList();
        }
        return sources.stream().map(t -> copyBean(t, supplier)).collect(Collectors.toList());
    }

    /**
     * @param sources  源对象
     * @param supplier 目标类
     * @date 2021/2/6
     */
    public static <S, T> List<T> copyList(List<S> sources, Supplier<T> supplier, Consumer<T> after) {
        if (CollectionUtils.isEmpty(sources)) {
            return Lists.newArrayList();
        }
        return sources.stream().map(t -> copyBean(t, supplier, after)).collect(Collectors.toList());
    }


}
